package cn.com.anypay.manager.payment.manager;

import cn.com.anypay.manager.payment.core.IPaymentChannel;
import cn.com.anypay.manager.payment.core.PaymentException;
import cn.com.anypay.manager.payment.core.AbstractPaymentChannelTemplate;
import cn.com.anypay.manager.payment.factory.PaymentProductFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

/**
 * 支付渠道管理器 - 统一的多实现架构
 * 由PaymentManager统一管理生命周期
 *
 * 负责支付渠道的注册、管理、路由和生命周期控制
 * 支持同一渠道的多种实现方式
 *
 * @author AnyPay Team
 * @version 1.0
 * @since 2025-07-05
 */
public class PaymentChannelManager {

    private static final Logger logger = LoggerFactory.getLogger(PaymentChannelManager.class);

    // 通过构造函数注入，而不是@Autowired
    private final PaymentProductFactory productFactory;

    /**
     * 多实现存储 - 唯一的渠道存储方式
     * Key: channelId_implementationType, Value: IPaymentChannel
     * 使用LinkedHashMap保持注册顺序
     */
    private final Map<String, IPaymentChannel> channelImplementations = new LinkedHashMap<>();

    /**
     * 渠道默认实现
     * Key: channelId, Value: implementationType
     * 使用LinkedHashMap保持注册顺序
     */
    private final Map<String, String> defaultImplementations = new LinkedHashMap<>();

    /**
     * 实现选择策略
     */
    public enum ImplementationStrategy {
        /** 固定使用默认实现 */
        FIXED,
        /** 故障转移 - 默认实现失败时使用备用实现 */
        FAILOVER,
        /** 轮询 - 轮流使用不同实现 */
        ROUND_ROBIN
    }

    /**
     * 渠道实现策略配置
     * Key: channelId, Value: ImplementationStrategy
     * 使用LinkedHashMap保持注册顺序
     */
    private final Map<String, ImplementationStrategy> implementationStrategies = new LinkedHashMap<>();

    /**
     * 轮询计数器
     * Key: channelId, Value: counter
     */
    private final Map<String, Integer> roundRobinCounters = new ConcurrentHashMap<>();

    /**
     * 读写锁，保证线程安全
     */
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    /**
     * 初始化标志
     */
    private volatile boolean initialized = false;

    /**
     * 构造函数 - 接受PaymentProductFactory注入
     */
    public PaymentChannelManager(PaymentProductFactory productFactory) {
        this.productFactory = productFactory;
        logger.debug("PaymentChannelManager 创建完成");
    }

    /**
     * 初始化方法 - 由PaymentManager调用
     */
    public void initialize() {
        if (initialized) {
            logger.warn("PaymentChannelManager already initialized");
            return;
        }

        logger.info("=== PaymentChannelManager 初始化开始 ===");
        initialized = true;
        logger.info("=== PaymentChannelManager 初始化完成 ===");
    }

    public void destroy() {
        logger.info("=== PaymentChannelManager 销毁开始 ===");

        lock.writeLock().lock();
        try {
            // 销毁所有渠道实现
            for (Map.Entry<String, IPaymentChannel> entry : channelImplementations.entrySet()) {
                try {
                    IPaymentChannel channel = entry.getValue();
                    if (channel != null) {
                        channel.destroy();
                        logger.debug("渠道实现 {} 销毁成功", entry.getKey());
                    }
                } catch (Exception e) {
                    logger.error("销毁渠道实现 {} 时发生错误", entry.getKey(), e);
                }
            }

            channelImplementations.clear();
            defaultImplementations.clear();
            implementationStrategies.clear();
            roundRobinCounters.clear();
            initialized = false;

        } finally {
            lock.writeLock().unlock();
        }

        logger.debug("=== PaymentChannelManager 销毁完成 ===");
    }

    /**
     * 注册渠道的特定实现
     *
     * @param channelId 渠道ID
     * @param implementationType 实现类型（如：impl1、impl2、default等）
     * @param channel 渠道实例
     * @throws PaymentException 注册失败时抛出
     */
    public void registerChannelImplementation(String channelId, String implementationType, IPaymentChannel channel) throws PaymentException {
        if (channelId == null || channelId.trim().isEmpty()) {
            throw new PaymentException("REGISTER_ERROR", "Channel ID is null or empty");
        }

        if (implementationType == null || implementationType.trim().isEmpty()) {
            throw new PaymentException("REGISTER_ERROR", "Implementation type is null or empty");
        }

        if (channel == null) {
            throw new PaymentException("REGISTER_ERROR", "Channel is null");
        }

        String key = channelId + "_" + implementationType;

        lock.writeLock().lock();
        try {
            // 检查是否已经注册
            if (channelImplementations.containsKey(key)) {
                logger.warn("渠道实现 {} 已经注册，将覆盖旧的实例", key);
                // 销毁旧的实例
                IPaymentChannel oldChannel = channelImplementations.get(key);
                if (oldChannel != null) {
                    oldChannel.destroy();
                }
            }

            // 设置ProductFactory（如果渠道继承自AbstractPaymentChannelTemplate）
            if (channel instanceof AbstractPaymentChannelTemplate && productFactory != null) {
                ((AbstractPaymentChannelTemplate) channel).setProductFactory(productFactory);
                logger.debug("为渠道实现 {} 设置ProductFactory", key);
            }

            // 初始化渠道
            channel.initialize();

            // 注册渠道实现
            channelImplementations.put(key, channel);

            // 如果是第一个实现，设置为默认实现
            if (!defaultImplementations.containsKey(channelId)) {
                defaultImplementations.put(channelId, implementationType);
                implementationStrategies.put(channelId, ImplementationStrategy.FIXED);
                logger.debug("设置渠道 {} 的默认实现为: {}", channelId, implementationType);
            }

            // 让渠道注册自己的产品
            if (productFactory != null) {
                try {
                    channel.registerProducts(productFactory);
                    logger.debug("渠道实现 {} ({}) 产品注册成功", key, channel.getChannelName());
                } catch (Exception e) {
                    logger.error("渠道实现 {} 注册产品失败", key, e);
                }
            }

            logger.info("渠道实现 {} ({}) 注册成功", key, channel.getChannelName());

        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 注销渠道实现
     *
     * @param channelId 渠道ID
     * @param implementationType 实现类型
     * @return 是否成功注销
     */
    public boolean unregisterChannelImplementation(String channelId, String implementationType) {
        if (channelId == null || channelId.trim().isEmpty() ||
            implementationType == null || implementationType.trim().isEmpty()) {
            return false;
        }

        String key = channelId + "_" + implementationType;

        lock.writeLock().lock();
        try {
            IPaymentChannel channel = channelImplementations.remove(key);
            if (channel != null) {
                try {
                    channel.destroy();
                    logger.info("渠道实现 {} 注销成功", key);

                    // 如果注销的是默认实现，需要重新设置默认实现
                    if (implementationType.equals(defaultImplementations.get(channelId))) {
                        List<String> remainingImplementations = getChannelImplementationTypes(channelId);
                        if (!remainingImplementations.isEmpty()) {
                            String newDefault = remainingImplementations.get(0);
                            defaultImplementations.put(channelId, newDefault);
                            logger.info("渠道 {} 默认实现更新为: {}", channelId, newDefault);
                        } else {
                            defaultImplementations.remove(channelId);
                            implementationStrategies.remove(channelId);
                            logger.info("渠道 {} 所有实现已注销", channelId);
                        }
                    }

                    return true;
                } catch (Exception e) {
                    logger.error("注销渠道实现 {} 时发生错误", key, e);
                    return false;
                }
            } else {
                logger.warn("渠道实现 {} 未注册", key);
                return false;
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 获取渠道的默认实现实例
     *
     * @param channelId 渠道ID
     * @return 渠道实例，如果不存在则返回null
     */
    public IPaymentChannel getChannel(String channelId) {
        if (channelId == null || channelId.trim().isEmpty()) {
            return null;
        }

        lock.readLock().lock();
        try {
            String defaultImpl = defaultImplementations.get(channelId);
            if (defaultImpl == null) {
                return null;
            }

            String key = channelId + "_" + defaultImpl;
            return channelImplementations.get(key);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取可用的支付渠道实例（使用默认实现）
     *
     * @param channelId 渠道ID
     * @return 可用的渠道实例
     * @throws PaymentException 渠道不存在或不可用时抛出
     */
    public IPaymentChannel getAvailableChannel(String channelId) throws PaymentException {
        IPaymentChannel channel = getChannel(channelId);

        if (channel == null) {
            throw new PaymentException("CHANNEL_NOT_FOUND", "Payment channel not found: " + channelId);
        }

        if (!channel.isAvailable()) {
            throw new PaymentException("CHANNEL_UNAVAILABLE", "Payment channel is not available: " + channelId);
        }

        return channel;
    }

    /**
     * 获取指定的渠道实现
     *
     * @param implementationKey 实现键（格式：channelId_implementationType）
     * @return 渠道实现实例，如果不存在则返回null
     */
    public IPaymentChannel getChannelImplementation(String implementationKey) {
        if (implementationKey == null || implementationKey.trim().isEmpty()) {
            return null;
        }

        lock.readLock().lock();
        try {
            return channelImplementations.get(implementationKey);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 检查渠道是否存在
     *
     * @param channelId 渠道ID
     * @return 是否存在
     */
    public boolean hasChannel(String channelId) {
        if (channelId == null || channelId.trim().isEmpty()) {
            return false;
        }

        lock.readLock().lock();
        try {
            return defaultImplementations.containsKey(channelId);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 检查渠道是否可用
     *
     * @param channelId 渠道ID
     * @return 是否可用
     */
    public boolean isChannelAvailable(String channelId) {
        IPaymentChannel channel = getChannel(channelId);
        return channel != null && channel.isAvailable();
    }

    /**
     * 获取所有注册的渠道ID
     *
     * @return 渠道ID数组
     */
    public String[] getAllChannelIds() {
        lock.readLock().lock();
        try {
            return defaultImplementations.keySet().toArray(new String[0]);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取所有可用的渠道ID
     *
     * @return 可用的渠道ID数组
     */
    public String[] getAvailableChannelIds() {
        lock.readLock().lock();
        try {
            return defaultImplementations.keySet().stream()
                    .filter(this::isChannelAvailable)
                    .toArray(String[]::new);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取渠道数量
     *
     * @return 渠道数量
     */
    public int getChannelCount() {
        lock.readLock().lock();
        try {
            return defaultImplementations.size();
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取可用渠道数量
     *
     * @return 可用渠道数量
     */
    public int getAvailableChannelCount() {
        lock.readLock().lock();
        try {
            return (int) defaultImplementations.keySet().stream()
                    .filter(this::isChannelAvailable)
                    .count();
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取渠道信息
     *
     * @param channelId 渠道ID
     * @return 渠道信息，如果不存在则返回null
     */
    public ChannelInfo getChannelInfo(String channelId) {
        IPaymentChannel channel = getChannel(channelId);
        if (channel == null) {
            return null;
        }

        return new ChannelInfo(
            channel.getChannelId(),
            channel.getChannelName(),
            channel.getVersion(),
            channel.isAvailable(),
            channel.getSupportedPayProducts()
        );
    }

    /**
     * 获取所有渠道信息
     *
     * @return 渠道信息数组
     */
    public ChannelInfo[] getAllChannelInfo() {
        lock.readLock().lock();
        try {
            return defaultImplementations.keySet().stream()
                    .map(this::getChannelInfo)
                    .filter(Objects::nonNull)
                    .toArray(ChannelInfo[]::new);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 检查管理器是否已初始化
     *
     * @return 是否已初始化
     */
    public boolean isInitialized() {
        return initialized;
    }

    // === 多实现支持方法 ===

    /**
     * 获取渠道的所有实现类型
     *
     * @param channelId 渠道ID
     * @return 实现类型列表
     */
    public List<String> getChannelImplementationTypes(String channelId) {
        if (channelId == null) {
            return new ArrayList<>();
        }

        lock.readLock().lock();
        try {
            String prefix = channelId + "_";
            return channelImplementations.keySet().stream()
                .filter(key -> key.startsWith(prefix))
                .map(key -> key.substring(prefix.length()))
                .collect(Collectors.toList());
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取渠道的所有实现实例
     *
     * @param channelId 渠道ID
     * @return 实现实例映射
     */
    public Map<String, IPaymentChannel> getChannelImplementations(String channelId) {
        if (channelId == null) {
            return new HashMap<>();
        }

        lock.readLock().lock();
        try {
            String prefix = channelId + "_";
            Map<String, IPaymentChannel> result = new HashMap<>();

            for (Map.Entry<String, IPaymentChannel> entry : channelImplementations.entrySet()) {
                if (entry.getKey().startsWith(prefix)) {
                    String implementationType = entry.getKey().substring(prefix.length());
                    result.put(implementationType, entry.getValue());
                }
            }

            return result;
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取渠道的默认实现类型
     *
     * @param channelId 渠道ID
     * @return 默认实现类型
     */
    public String getDefaultImplementation(String channelId) {
        lock.readLock().lock();
        try {
            return defaultImplementations.get(channelId);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 设置渠道的默认实现
     *
     * @param channelId 渠道ID
     * @param implementationType 实现类型
     * @return 是否设置成功
     */
    public boolean setDefaultImplementation(String channelId, String implementationType) {
        if (channelId == null || implementationType == null) {
            return false;
        }

        lock.writeLock().lock();
        try {
            String key = channelId + "_" + implementationType;
            if (channelImplementations.containsKey(key)) {
                defaultImplementations.put(channelId, implementationType);
                logger.info("渠道 {} 默认实现设置为: {}", channelId, implementationType);
                return true;
            } else {
                logger.warn("渠道实现 {} 不存在，无法设置为默认实现", key);
                return false;
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 获取渠道的实现策略
     *
     * @param channelId 渠道ID
     * @return 实现策略
     */
    public ImplementationStrategy getImplementationStrategy(String channelId) {
        lock.readLock().lock();
        try {
            return implementationStrategies.getOrDefault(channelId, ImplementationStrategy.FIXED);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 设置渠道的实现策略
     *
     * @param channelId 渠道ID
     * @param strategy 实现策略
     */
    public void setImplementationStrategy(String channelId, ImplementationStrategy strategy) {
        if (channelId == null || strategy == null) {
            return;
        }

        lock.writeLock().lock();
        try {
            if (defaultImplementations.containsKey(channelId)) {
                implementationStrategies.put(channelId, strategy);
                logger.info("渠道 {} 实现策略设置为: {}", channelId, strategy);
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    // === 内部类 ===

    /**
     * 渠道信息类
     */
    public static class ChannelInfo {
        private final String channelId;
        private final String channelName;
        private final String version;
        private final boolean available;
        private final String[] supportedPayMethods;

        public ChannelInfo(String channelId, String channelName, String version, boolean available, String[] supportedPayMethods) {
            this.channelId = channelId;
            this.channelName = channelName;
            this.version = version;
            this.available = available;
            this.supportedPayMethods = supportedPayMethods;
        }

        public String getChannelId() {
            return channelId;
        }

        public String getChannelName() {
            return channelName;
        }

        public String getVersion() {
            return version;
        }

        public boolean isAvailable() {
            return available;
        }

        public String[] getSupportedPayMethods() {
            return supportedPayMethods;
        }

        @Override
        public String toString() {
            return "ChannelInfo{" +
                    "channelId='" + channelId + '\'' +
                    ", channelName='" + channelName + '\'' +
                    ", version='" + version + '\'' +
                    ", available=" + available +
                    ", supportedPayMethods=" + java.util.Arrays.toString(supportedPayMethods) +
                    '}';
        }
    }

    /**
     * 增强的渠道信息类
     */
    public static class EnhancedChannelInfo extends ChannelInfo {
        private final List<String> implementations;
        private final String defaultImplementation;
        private final ImplementationStrategy strategy;

        public EnhancedChannelInfo(String channelId, String channelName, String version,
            boolean available, String[] supportedPayMethods,
            List<String> implementations, String defaultImplementation, ImplementationStrategy strategy) {
            super(channelId, channelName, version, available, supportedPayMethods);
            this.implementations = implementations;
            this.defaultImplementation = defaultImplementation;
            this.strategy = strategy;
        }

        public List<String> getImplementations() {
            return implementations;
        }

        public String getDefaultImplementation() {
            return defaultImplementation;
        }

        public ImplementationStrategy getStrategy() {
            return strategy;
        }

        public int getImplementationCount() {
            return implementations != null ? implementations.size() : 0;
        }

        public boolean hasMultipleImplementations() {
            return getImplementationCount() > 1;
        }

        @Override
        public String toString() {
            return "EnhancedChannelInfo{" +
                    "channelId='" + getChannelId() + '\'' +
                    ", channelName='" + getChannelName() + '\'' +
                    ", version='" + getVersion() + '\'' +
                    ", available=" + isAvailable() +
                    ", supportedPayMethods=" + java.util.Arrays.toString(getSupportedPayMethods()) +
                    ", implementations=" + implementations +
                    ", defaultImplementation='" + defaultImplementation + '\'' +
                    ", strategy=" + strategy +
                    '}';
        }
    }

    /**
     * 获取增强的渠道信息
     *
     * @param channelId 渠道ID
     * @return 增强的渠道信息
     */
    public EnhancedChannelInfo getEnhancedChannelInfo(String channelId) {
        IPaymentChannel channel = getChannel(channelId);
        if (channel == null) {
            return null;
        }

        List<String> implementations = getChannelImplementationTypes(channelId);
        String defaultImpl = getDefaultImplementation(channelId);
        ImplementationStrategy strategy = getImplementationStrategy(channelId);

        return new EnhancedChannelInfo(
            channel.getChannelId(),
            channel.getChannelName(),
            channel.getVersion(),
            channel.isAvailable(),
            channel.getSupportedPayProducts(),
            implementations,
            defaultImpl,
            strategy
        );
    }

    /**
     * 获取所有渠道的增强信息
     *
     * @return 增强渠道信息数组
     */
    public EnhancedChannelInfo[] getAllEnhancedChannelInfo() {
        lock.readLock().lock();
        try {
            return defaultImplementations.keySet().stream()
                .map(this::getEnhancedChannelInfo)
                .filter(Objects::nonNull)
                .toArray(EnhancedChannelInfo[]::new);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取所有渠道实现信息（按注册顺序）
     *
     * @return 渠道实现信息数组
     */
    public ChannelImplementationInfo[] getAllChannelImplementationInfoInOrder() {
        lock.readLock().lock();
        try {
            List<ChannelImplementationInfo> result = new ArrayList<>();

            for (Map.Entry<String, IPaymentChannel> entry : channelImplementations.entrySet()) {
                String key = entry.getKey();
                IPaymentChannel channel = entry.getValue();

                if (key.contains("_")) {
                    String channelId = key.substring(0, key.indexOf("_"));
                    String implementationType = key.substring(key.indexOf("_") + 1);
                    boolean isDefault = implementationType.equals(defaultImplementations.get(channelId));

                    ChannelImplementationInfo info = new ChannelImplementationInfo(
                        key,
                        channelId,
                        implementationType,
                        channel.getChannelName(),
                        channel.isAvailable(),
                        channel.getSupportedPayProducts(),
                        isDefault
                    );
                    result.add(info);
                }
            }

            return result.toArray(new ChannelImplementationInfo[0]);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 渠道实现信息类
     */
    public static class ChannelImplementationInfo {
        private final String implementationKey;
        private final String channelId;
        private final String implementationType;
        private final String channelName;
        private final boolean available;
        private final String[] supportedPayProducts;
        private final boolean isDefault;

        public ChannelImplementationInfo(String implementationKey, String channelId, String implementationType,
                                       String channelName, boolean available, String[] supportedPayProducts, boolean isDefault) {
            this.implementationKey = implementationKey;
            this.channelId = channelId;
            this.implementationType = implementationType;
            this.channelName = channelName;
            this.available = available;
            this.supportedPayProducts = supportedPayProducts;
            this.isDefault = isDefault;
        }

        public String getImplementationKey() {
            return implementationKey;
        }

        public String getChannelId() {
            return channelId;
        }

        public String getImplementationType() {
            return implementationType;
        }

        public String getChannelName() {
            return channelName;
        }

        public boolean isAvailable() {
            return available;
        }

        public String[] getSupportedPayProducts() {
            return supportedPayProducts;
        }

        public boolean isDefault() {
            return isDefault;
        }

        @Override
        public String toString() {
            return "ChannelImplementationInfo{" +
                    "implementationKey='" + implementationKey + '\'' +
                    ", channelId='" + channelId + '\'' +
                    ", implementationType='" + implementationType + '\'' +
                    ", channelName='" + channelName + '\'' +
                    ", available=" + available +
                    ", supportedPayProducts=" + Arrays.toString(supportedPayProducts) +
                    ", isDefault=" + isDefault +
                    '}';
        }
    }
}